#include "tapp.h"
#include "tapi32u8.h"
#include "tapi32ex.h"

TApp *TApp::tapp = NULL;
#define MAX_TAPPWIN_HASH	1009
#define ENGLISH_TEST		0

TApp::TApp( HINSTANCE hInstance, LPSTR cmdLine, int cmdShow )
: _hInstance( hInstance )
, _cmdLine( cmdLine )
, _cmdShow( cmdShow )
, _mainWnd( NULL )
, _hash( new TWinHashTbl( MAX_TAPPWIN_HASH ) )
{
	_defaultClass = "tapp";
	_defaultClassV = TAPI32V::IS_WINNT_V ? (void*)L"tapp" : (void*)"tapp";
	tapp = this;

	InitInstanceForLoadStr( hInstance );
	TAPI32V::TLibInit_Win32V();

#if ENGLISH_TEST
	TSetDefaultLCID( 0x409 );
#else
	TSetDefaultLCID();
#endif
	::CoInitialize( NULL );
	::InitCommonControls();
}

TApp::~TApp()
{
	delete _mainWnd;
	delete _hash;
	::CoUninitialize();
}

int TApp::Run()
{
	MSG msg;

	InitApp();
	InitWindow();

	while( ::GetMessage( &msg, NULL, 0, 0 ) )
	{
		if( PreProcMsg( &msg ) )
			continue;
		::TranslateMessage( &msg );
		::DispatchMessage( &msg );
	}
	return (int)msg.wParam;
}

BOOL TApp::InitApp()
{
	WNDCLASS wc;
	memset( &wc, 0, sizeof(WNDCLASS) );
	wc.style			= (CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_DBLCLKS);
	wc.lpfnWndProc		= WinProc;
	wc.cbClsExtra 		= 0;
	wc.cbWndExtra		= 0;
	wc.hInstance		= _hInstance;
	wc.hIcon			= NULL;
	wc.hCursor			= LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground	= NULL;
	wc.lpszMenuName		= NULL;
	wc.lpszClassName	= (LPCSTR)_defaultClassV;
	if( TAPI32V::FindWindowV( _defaultClassV, NULL ) == NULL )
		if( TAPI32V::RegisterClassV( &wc ) == 0 )
			return FALSE;

	return TRUE;
}

BOOL TApp::PreProcMsg( MSG* msg )
{
	for( HWND hWnd = msg->hwnd; hWnd != NULL; hWnd = ::GetParent( hWnd ) )
	{
		TWin* win = SearchWnd( hWnd );
		if( win != NULL ) win->PreProcMsg( msg );
	}
	return FALSE;
}

LRESULT CALLBACK TApp::WinProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
	TApp* app = TApp::GetApp();
	TWin* win = app->SearchWnd( hWnd );
	if( win != NULL ) win->WinProc( uMsg, wParam, lParam );

	win = app->_preWnd;
	if( win != NULL )
	{
		app->_preWnd = NULL;
		app->AddWinByWnd( win, hWnd );
		return win->WinProc( uMsg, wParam, lParam );
	}

	return ::DefWindowProc( hWnd, uMsg, wParam, lParam );
}

BOOL TRegisterClass( LPCSTR class_name, UINT style /* = CS_DBLCLKS */, HICON hIcon /* = 0 */, 
					HCURSOR hCursor /* = 0 */, HBRUSH hbrBackground /* = 0 */, int classExtra /* = 0 */, 
					int wndExtra /* = 0 */, LPCSTR menu_str /* = 0 */ )
{
	WNDCLASS	wc;

	memset(&wc, 0, sizeof(wc));
	wc.style			= style;
	wc.lpfnWndProc		= TApp::WinProc;
	wc.cbClsExtra 		= classExtra;
	wc.cbWndExtra		= wndExtra;
	wc.hInstance		= TApp::GetInstance();
	wc.hIcon			= hIcon;
	wc.hCursor			= hCursor;
	wc.hbrBackground	= hbrBackground;
	wc.lpszMenuName		= menu_str;
	wc.lpszClassName	= class_name;

	return	::RegisterClass(&wc);
}

BOOL TRegisterClassV(const void *class_name, UINT style, HICON hIcon, HCURSOR hCursor,
					 HBRUSH hbrBackground, int classExtra, int wndExtra, const void *menu_str)
{
	WNDCLASSW	wc;

	memset(&wc, 0, sizeof(wc));
	wc.style			= style;
	wc.lpfnWndProc		= TApp::WinProc;
	wc.cbClsExtra 		= classExtra;
	wc.cbWndExtra		= wndExtra;
	wc.hInstance		= TApp::GetInstance();
	wc.hIcon			= hIcon;
	wc.hCursor			= hCursor;
	wc.hbrBackground	= hbrBackground;
	wc.lpszMenuName		= (LPCWSTR)menu_str;
	wc.lpszClassName	= (LPCWSTR)class_name;

	return	TAPI32V::RegisterClassV(&wc);
}

BOOL TRegisterClassU8(LPCSTR class_name, UINT style, HICON hIcon, HCURSOR hCursor,
					  HBRUSH hbrBackground, int classExtra, int wndExtra, LPCSTR menu_str)
{
	Wstr	class_name_w(class_name, BY_UTF8);
	Wstr	menu_str_w(menu_str, BY_UTF8);

	return	TRegisterClassV(class_name_w, style, hIcon, hCursor, hbrBackground, classExtra,
		wndExtra, menu_str_w);
}